package com.example.stripe_terminal_usb;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.google.firebase.crashlytics.buildtools.reloc.com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.stripe.stripeterminal.Terminal;
import com.stripe.stripeterminal.TerminalApplicationDelegate;
import com.stripe.stripeterminal.external.callable.Callback;
import com.stripe.stripeterminal.external.callable.Cancelable;
import com.stripe.stripeterminal.external.callable.ConnectionTokenCallback;
import com.stripe.stripeterminal.external.callable.ConnectionTokenProvider;
import com.stripe.stripeterminal.external.callable.DiscoveryListener;
import com.stripe.stripeterminal.external.callable.PaymentIntentCallback;
import com.stripe.stripeterminal.external.callable.ReaderCallback;
import com.stripe.stripeterminal.external.callable.ReaderListener;
import com.stripe.stripeterminal.external.callable.ReaderReconnectionListener;
import com.stripe.stripeterminal.external.callable.TerminalListener;
import com.stripe.stripeterminal.external.models.BatteryStatus;
import com.stripe.stripeterminal.external.models.CollectConfiguration;
import com.stripe.stripeterminal.external.models.ConnectionConfiguration;
import com.stripe.stripeterminal.external.models.ConnectionStatus;
import com.stripe.stripeterminal.external.models.DisconnectReason;
import com.stripe.stripeterminal.external.models.DiscoveryConfiguration;
import com.stripe.stripeterminal.external.models.PaymentIntent;
import com.stripe.stripeterminal.external.models.Reader;
import com.stripe.stripeterminal.external.models.TerminalException;
import com.stripe.stripeterminal.log.LogLevel;
import com.sunmi.printerx.PrinterSdk;
import com.sunmi.printerx.api.PrintResult;

import org.jetbrains.annotations.NotNull;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.flutter.app.FlutterActivityEvents;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry;

/** StripeTerminalUsbPlugin */
public class StripeTerminalUsbPlugin extends Application implements FlutterPlugin, MethodCallHandler, PluginRegistry.RequestPermissionsResultListener, ActivityAware, FlutterActivityEvents {
  private static final int REQUEST_CODE_LOCATION = 1012;
  private Activity currentActivity = new Activity();

  private List<String> permissions;
  private MethodChannel channel;

  /**stripe localId*/
  private String localId;

  /**获取stripeToken服务器Url*/
  private String tokenUrl;
  private String departId;
  private Cancelable discoveryCancelable;
  private PaymentIntent currentPaymentIntent;
  private Cancelable collectPaymentMethod;
  private Context context;
  /**
   * 指定操作的商米打印机设备
   */
  public PrinterSdk.Printer selectPrinter;



  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    context = flutterPluginBinding.getApplicationContext();
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "stripe_terminal_usb");
    channel.setMethodCallHandler(this);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
      String[] array = {Manifest.permission.ACCESS_FINE_LOCATION,
              Manifest.permission.INTERNET,
              Manifest.permission.ACCESS_NETWORK_STATE,
              Manifest.permission.ACCESS_WIFI_STATE,
              Manifest.permission.ACCESS_COARSE_LOCATION,
              Manifest.permission.READ_PHONE_STATE
      };
      permissions = Arrays.asList(array);
    } else {
      String[] array = {Manifest.permission.ACCESS_FINE_LOCATION,
              Manifest.permission.INTERNET,
              Manifest.permission.ACCESS_NETWORK_STATE,
              Manifest.permission.ACCESS_WIFI_STATE,
              Manifest.permission.READ_PHONE_STATE,
              Manifest.permission.ACCESS_COARSE_LOCATION
      };
      permissions = Arrays.asList(array);
    }
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    switch (call.method) {
      case "permissionAllowed":
        _isPermissionAllowed(result);
        break;
      case "init":
        this.localId = call.argument("localId");
        this.tokenUrl = call.argument("tokenUrl");
        this.departId = call.argument("departId");
        init();
        break;
      case "connectReaders":
        onStart();
        break;
      case "pay":
        String clientSecret = call.argument("clientSecret");
        Map<String, Object> collectConfiguration = call.argument("collectConfiguration");
        if (clientSecret != null) {
          pay(clientSecret, collectConfiguration, result);
        } else {
          result.error(
                  "stripeTerminal#invalidPaymentIntentClientSecret",
                  "The payment intent client_secret seems to be invalid or missing.",
                  null
          );
        }
        break;
      case "processPayment":
        processPayment(result);
        break;
      case "cancelRetrievePaymentIntent":
        cancelRetrievePaymentIntent(result);
        break;
      case "cancelProcessPayment":
        cancelProcessPayment(result);
        break;
      case "initOpenCash":
        //初始化连接钱箱
        initOpenCash(result);
        break;
      case "openCash":
        //打开钱箱
        openCash(result);
        break;

    }
  }

  private void initOpenCash(Result result) {
    try {
      PrinterSdk.getInstance().getPrinter(context, new PrinterSdk.PrinterListen() {
        @Override
        public void onDefPrinter(PrinterSdk.Printer printer) {
          selectPrinter = printer;
          result.success(true);
        }
        @Override
        public void onPrinters(List<PrinterSdk.Printer> printers) {

        }
      });
    } catch (Exception e) {
      result.error(
              "stripeTerminal#InitOpenTheCashDrawer",
              e.getMessage(),
              null
      );
      throw new RuntimeException(e);
    }
  }

  private void openCash(Result result) {
    if (selectPrinter == null){
      result.error(
              "stripeTerminal#OpenTheCashDrawer",
              "SUNMI cash drawer is not initialized",
              null
      );
      return;
    }
    try {
      selectPrinter.cashDrawerApi().open(new PrintResult() {
        @Override
        public void onResult(int resultCode, String message)  {
          Map<String,Object> map = new HashMap<>();
          map.put("status","succeed");
          map.put("resultCode",resultCode);
          map.put("message",message);
          result.success(map);
        }
      });
    } catch (Exception e) {
      result.error(
              "stripeTerminal#OpenTheCashDrawer",
              e.getMessage(),
              null
      );
      throw new RuntimeException(e);
    }
  }

  /**
   * 获取权限
   * @param result
   * @return
   */
  private Boolean _isPermissionAllowed(Result result) {
    List<Integer> permissionStatus = new ArrayList<>();
    List<Boolean> cannotAskPermissions = new ArrayList<>();
    for (String item : permissions) {
      permissionStatus.add(ContextCompat.checkSelfPermission(currentActivity, item));
      cannotAskPermissions.add(ActivityCompat.shouldShowRequestPermissionRationale(currentActivity, item));
    }
    if (!permissionStatus.contains(PackageManager.PERMISSION_DENIED)) {
      return true;
    }
    if (cannotAskPermissions.contains(true)) {
      return false;
    }
    ActivityCompat.requestPermissions(currentActivity,
            (String[]) permissions.toArray(),
            REQUEST_CODE_LOCATION);
    final LocationManager locationManager =
            (LocationManager) currentActivity.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
    boolean gpsEnabled = false;
    try {
      gpsEnabled = locationManager != null &&
              locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    } catch (Exception exception) {
    }
    result.success(gpsEnabled);
    return gpsEnabled;
  }

  /**
   * 获取token
   * @return
   */
  private String getToken() {
    HttpURLConnection connection = null;
    try {
      URL url = new URL(tokenUrl);
      connection = (HttpURLConnection) url.openConnection();
      //GET请求
      connection.setRequestMethod("POST");
      String postParams = "departId=" + URLEncoder.encode(departId, "UTF-8");
      OutputStream os = connection.getOutputStream();
      os.write(postParams.getBytes());
      os.flush();

      //获取数据成功
      if (HttpURLConnection.HTTP_OK == connection.getResponseCode()) {
        //服务器响应返回的字节流
        InputStream inputStream = connection.getInputStream();
        //转换成字符流
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));

        StringBuilder response = new StringBuilder();
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
          response.append(line);
        }
        //关闭io流
        inputStream.close();
        bufferedReader.close();
        Map<String, String> stringStringMap = stringToMap(response.toString());
        if (stringStringMap.containsKey("result")) {
          String result = stringStringMap.get("result");
          if (result != null && !result.equals("null")) {
            return result;
          }
        }
      }
    } catch (Exception e) {
      currentActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
          channel.invokeMethod("onErrorLog", "fetchConnectionToken()" + e.getMessage());
        }
      });
      return null;
    } finally {
      if (null != connection) {
        connection.disconnect();
      }
    }
    return null;
  }

  private Map<String, String> stringToMap(String param) {
    Map<String, String> map = new HashMap<>();
    //去除{}
    String s1 = param.replace("{", "");
    String s2 = s1.replace("}", "");
    String s3 = s2.trim();

    //1.根据逗号分隔
    String[] split = s3.split(",");
    for (int i = split.length - 1; i >= 0; i--) {
      String trim = split[i].trim();
      String[] split1 = trim.split(":");
      map.put(split1[0].replace("\"", ""), split1[1].replace("\"", ""));
    }
    return map;
  }

  /**
   * 初始化
   */
  private void init() {
    try {
      if (!Terminal.isInitialized()) {
        Terminal.initTerminal(currentActivity.getApplicationContext(), LogLevel.VERBOSE, new ConnectionTokenProvider() {
          @Override
          public void fetchConnectionToken(@NonNull ConnectionTokenCallback connectionTokenCallback) {
            while (true) {
              String token = getToken();
              if (token == null || token.isEmpty()) {
                currentActivity.runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                    Map<String, Object> data = new HashMap<>();
                    data.put("status", "tokenError");
                    data.put("msg", "获取token失败");
                    channel.invokeMethod("connectReadersStatus", data);
                  }
                });
              } else {
                connectionTokenCallback.onSuccess(token);
                currentActivity.runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                    Map<String, Object> data = new HashMap<>();
                    data.put("status", "tokenSucceed");
                    data.put("msg", "获取token成功");
                    channel.invokeMethod("connectReadersStatus", data);
                  }
                });
                break;
              }
            }
          }
        }, new TerminalListener() {
          @Override
          public void onUnexpectedReaderDisconnect(@NonNull Reader reader) {
            currentActivity.runOnUiThread(new Runnable() {
              @Override
              public void run() {
                Map<String, Object> data = new HashMap<>();
                data.put("status", "readerDisconnect");
                data.put("msg", "连接断开");
                channel.invokeMethod("connectReadersStatus", data);
              }
            });
          }

          @Override
          public void onConnectionStatusChange(@NotNull ConnectionStatus status) {
            currentActivity.runOnUiThread(new Runnable() {
              @Override
              public void run() {
                Map<String, Object> data = new HashMap<>();
                data.put("status", "connectionStatus");
                data.put("data", status.toString());
                channel.invokeMethod("connectReadersStatus", data);
              }
            });
          }
        });
        onStart();
      }
    } catch (TerminalException e) {
      currentActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
          Map<String, Object> data = new HashMap<>();
          data.put("status", "tokenError");
          data.put("msg", "初始化失败"  +  e.getMessage());
          channel.invokeMethod("connectReadersStatus", data);
        }
      });
      throw new RuntimeException("Location services are required in order to initialize the Terminal.", e);
    }
  }

  /**
   * 连接设备
   * @param connectionReader
   */
  private void connection(Reader connectionReader) {
    Terminal.getInstance().connectUsbReader(connectionReader, new ConnectionConfiguration.UsbConnectionConfiguration(localId, true, new ReaderReconnectionListener() {
      @Override
      public void onReaderReconnectStarted(@NonNull Reader reader, @NonNull Cancelable cancelReconnect, @NonNull DisconnectReason reason) {
        ReaderReconnectionListener.super.onReaderReconnectStarted(reader, cancelReconnect, reason);
        currentActivity.runOnUiThread(new Runnable() {
          @Override
          public void run() {
            Map<String, Object> data = new HashMap<>();
            data.put("status", "onReaderReconnectStarted");
            data.put("msg", "正在尝试重连");
            channel.invokeMethod("connectReadersStatus", data);
          }
        });
      }

      @Override
      public void onReaderReconnectSucceeded(@NonNull Reader reader) {
        currentActivity.runOnUiThread(new Runnable() {
          @Override
          public void run() {
            Map<String, Object> data = new HashMap<>();
            data.put("status", "onReaderReconnectSucceeded");
            data.put("msg", "重连成功");
            channel.invokeMethod("connectReadersStatus", data);
          }
        });
      }

      @Override
      public void onReaderReconnectFailed(@NonNull Reader reader) {
        onStart();
        currentActivity.runOnUiThread(new Runnable() {
          @Override
          public void run() {
            Map<String, Object> data = new HashMap<>();
            data.put("status", "onReaderReconnectFailed");
            data.put("msg", "意外断开");
            channel.invokeMethod("connectReadersStatus", data);
          }
        });
      }
    }), new ReaderListener() {
      @Override
      public void onBatteryLevelUpdate(float batteryLevel, @NonNull BatteryStatus batteryStatus, boolean isCharging) {
        ReaderListener.super.onBatteryLevelUpdate(batteryLevel, batteryStatus, isCharging);
        currentActivity.runOnUiThread(new Runnable() {
          @Override
          public void run() {
            channel.invokeMethod("onBatteryLevel", batteryLevel);
          }
        });
      }

      @Override
      public void onReportLowBatteryWarning() {
        currentActivity.runOnUiThread(new Runnable() {
          @Override
          public void run() {
            channel.invokeMethod("onBatteryWarning", "电量不足警告,请及时充电");
          }
        });
      }

    }, new ReaderCallback() {
      @Override
      public void onSuccess(@NonNull Reader reader) {
        onStop();
        currentActivity.runOnUiThread(new Runnable() {
          @Override
          public void run() {
            Map<String, Object> data = new HashMap<>();
            data.put("status", "connectionSuccess");
            data.put("msg", "连接设备完成");
            channel.invokeMethod("connectReadersStatus", data);
          }
        });
      }

      @Override
      public void onFailure(@NonNull TerminalException e) {
        onStart();
        currentActivity.runOnUiThread(new Runnable() {
          @Override
          public void run() {
            Map<String, Object> data = new HashMap<>();
            data.put("status", "connectionError");
            data.put("msg", e.getErrorMessage());
            channel.invokeMethod("connectReadersStatus", data);
          }
        });
      }
    });
  }


  /**
   * 支付
   * @param clientSecret
   * @param result
   */
  public void pay(String clientSecret, Map<String, Object> collectConfiguration, Result result) {
    if (Terminal.getInstance().getConnectedReader() == null) {
      result.error(
              "stripeTerminal#deviceNotConnected",
              "You must connect to a device before you can use it.",
              null
      );
    } else {
      Terminal.getInstance().retrievePaymentIntent(clientSecret, new PaymentIntentCallback() {
        @Override
        public void onSuccess(@NonNull PaymentIntent paymentIntent) {
          currentPaymentIntent = paymentIntent;
          CollectConfiguration collectConfig = new CollectConfiguration.Builder()
                  .updatePaymentIntent(true)
                  .skipTipping((Boolean) collectConfiguration.get("skipTipping"))
                  .build();
          collectPaymentMethod = Terminal.getInstance().collectPaymentMethod(paymentIntent,
                  new PaymentIntentCallback() {
                    @Override
                    public void onSuccess(@NonNull PaymentIntent paymentIntent) {
                      currentPaymentIntent = paymentIntent;
                      // Placeholder for confirming paymentIntent
                      Gson gson = new Gson();
                      result.success(gson.fromJson(gson.toJson(paymentIntent), new TypeToken<Map<String, Object>>() {
                      }.getType()));
                    }

                    @Override
                    public void onFailure(@NonNull TerminalException e) {

                      result.error(
                              "stripeTerminal#unableToCollectPaymentMethod",
                              "Stripe reader was not able to collect the payment method for the provided payment intent. ${e.errorMessage}",
                              e.getErrorMessage()
                      );
                      // Placeholder for handling exception
                    }
                  }, collectConfig);
        }

        @Override
        public void onFailure(@NonNull TerminalException e) {
          result.error(
                  "stripeTerminal#unableToRetrivePaymentIntent",
                  "Stripe was not able to fetch the payment intent with the provided client secret. ${e.errorMessage}",
                  e.getErrorMessage()
          );
          // Placeholder for handling exception
        }
      });
    }
  }

  private void processPayment(Result result) {
    if (currentPaymentIntent == null) {
      result.error(
              "stripeTerminal#unableToProcessPayment",
              "Stripe reader was not able to process the payment for the provided payment intent",
              null
      );
      return;
    }
    Terminal.getInstance().confirmPaymentIntent(currentPaymentIntent,
            new PaymentIntentCallback() {
              @Override
              public void onSuccess(@NonNull PaymentIntent paymentIntent) {
                currentPaymentIntent = null;
                // Placeholder for notifying your backend to capture paymentIntent.id
                //TODO : Return to previous Screen
                Gson gson = new Gson();
                result.success(gson.fromJson(gson.toJson(paymentIntent), new TypeToken<Map<String, Object>>() {
                }.getType()));
              }

              @Override
              public void onFailure(@NonNull TerminalException e) {
                currentPaymentIntent = null;
                result.error(
                        "stripeTerminal#unableToProcessPayment",
                        "Stripe reader was not able to process the payment for the provided payment intent. - " + e.getErrorMessage(),
                        e.getErrorMessage()
                );
              }
            });
  }

  /**
   * 取消检索刷卡状态
   */
  private void cancelRetrievePaymentIntent(Result result) {
    if (collectPaymentMethod == null) {
      result.error(
              "stripeTerminal#unabelToCancelDiscover",
              "There is no discover action running to stop.",
              null
      );
    } else {
      collectPaymentMethod.cancel(new Callback() {
        @Override
        public void onFailure(@NonNull TerminalException e) {
          result.error(
                  "stripeTerminal#unabelToCancelDiscover",
                  "Unable to stop the discover action because ${e.errorMessage}",
                  e.getErrorMessage()
          );
        }

        @Override
        public void onSuccess() {
          result.success(true);
        }
      });
      collectPaymentMethod = null;
    }
  }


  /**
   * 取消付款意向
   */
  private void cancelProcessPayment(Result result) {
    if (currentPaymentIntent == null) {
      result.error(
              "stripeTerminal#unableToProcessPayment",
              "Stripe reader was not able to process the payment for the provided payment intent",
              null
      );
      return;
    }
    if (Terminal.isInitialized()) {
      Terminal.getInstance()
              .cancelPaymentIntent(
                      currentPaymentIntent,
                      new PaymentIntentCallback() {
                        @Override
                        public void onSuccess(PaymentIntent intent) {

                          currentPaymentIntent = null;
                          Gson gson = new Gson();
                          result.success(gson.fromJson(gson.toJson(intent), new TypeToken<Map<String, Object>>() {
                          }.getType()));
                        }

                        @Override
                        public void onFailure(TerminalException e) {
                          currentPaymentIntent = null;
                          result.error(
                                  "stripeTerminal#unableToProcessPayment",
                                  "Stripe reader was not able to process the payment for the provided payment intent. ${e.errorMessage}",
                                  e.getErrorMessage()
                          );
                        }
                      });
    } else {
      result.error("InitializationError", "设备未初始化", null);
    }
  }


  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }

  @Override
  public void onCreate(Bundle bundle) {
    // Should happen before super.onCreate()
    StrictMode.setThreadPolicy(
            new StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectAll()
                    .penaltyLog()
                    .build());

    StrictMode.setVmPolicy(
            new StrictMode.VmPolicy.Builder()
                    .detectLeakedSqlLiteObjects()
                    .detectLeakedClosableObjects()
                    .penaltyLog()
                    .build());
    super.onCreate();
    TerminalApplicationDelegate.onCreate(this);
  }

  @Override
  public void onNewIntent(Intent intent) {

  }

  @Override
  public void onPause() {

  }

  /**
   * 发现设备并连接
   */
  @SuppressLint("MissingPermission")
  @Override
  public void onStart() {
    if (Terminal.isInitialized()) {
      final DiscoveryConfiguration config = new DiscoveryConfiguration.UsbDiscoveryConfiguration(5, false);
      discoveryCancelable = Terminal.getInstance().discoverReaders(
              config,
              new DiscoveryListener() {
                @Override
                public void onUpdateDiscoveredReaders(@NonNull List<Reader> list) {
                  if (!list.isEmpty()) {
                    connection(list.get(0));
                  }
                }
              },
              new Callback() {
                @Override
                public void onSuccess() {
                  currentActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                      Map<String, Object> data = new HashMap<>();
                      data.put("status", "discoverReadersSuccess");
                      data.put("msg", "已发现设备");
                      channel.invokeMethod("connectReadersStatus", data);
                    }
                  });
                }

                @Override
                public void onFailure(@NonNull TerminalException e) {
                  if (!e.getErrorCode().toString().equals(TerminalException.TerminalErrorCode.ALREADY_CONNECTED_TO_READER.toString())) {
                    onStart();
                  }
                  currentActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                      Map<String, Object> data = new HashMap<>();
                      data.put("status", "discoverReadersError");
                      data.put("msg", e.getErrorCode().toString() + " : " + e.getErrorMessage());
                      channel.invokeMethod("connectReadersStatus", data);
                    }
                  });
                }
              }
      );
    }else {
      init();
    }
  }

  @Override
  public void onResume() {

  }

  @Override
  public void onPostResume() {

  }

  @Override
  public void onDestroy() {

  }

  @Override
  public void onStop() {
    // 如果您要离开活动或片段而不选择读者
    // 请确保取消发现过程，否则 SDK 将卡在
    //“发现读者”阶段
    if (discoveryCancelable != null) {
      discoveryCancelable.cancel(new Callback() {
        @Override
        public void onSuccess() {
          discoveryCancelable = null;
        }

        @Override
        public void onFailure(@NonNull TerminalException e) {
          discoveryCancelable = null;
          currentActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
              channel.invokeMethod("onErrorLog", "discoverReadersStop"+e.getErrorMessage());
            }
          });
        }
      });
    }
  }

  @Override
  public boolean onBackPressed() {
    return false;
  }

  @Override
  public void onUserLeaveHint() {

  }

  @Override
  public void onWindowFocusChanged(boolean b) {

  }

  @Override
  public void onTrimMemory(int i) {
    super.onTrimMemory(i);
  }

  @Override
  public void onConfigurationChanged(@NonNull Configuration configuration) {
    super.onConfigurationChanged(configuration);
  }

  @Override
  public void onLowMemory() {
    super.onLowMemory();
  }

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) {
    currentActivity = activityPluginBinding.getActivity();
    activityPluginBinding.addRequestPermissionsResultListener(this);
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {
    currentActivity = null;
  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding activityPluginBinding) {
    currentActivity = activityPluginBinding.getActivity();
  }

  @Override
  public void onDetachedFromActivity() {

  }

  @Override
  public boolean onActivityResult(int i, int i1, @Nullable Intent intent) {
    return false;
  }

  @Override
  public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] strings, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_CODE_LOCATION && grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
      throw new RuntimeException("Location services are required in order to connect to a reader.");
    }
    List<Integer> permissionStatus = new ArrayList<>();
    for (String item : permissions) {
      permissionStatus.add(ContextCompat.checkSelfPermission(currentActivity, item));
    }
    if (permissionStatus.contains(PackageManager.PERMISSION_DENIED)) {
      return false;
    }
    return requestCode == REQUEST_CODE_LOCATION;
  }
}
